package com.nifostasky.dlx.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * 延迟队列配置
 * TTL + DLX(生存时间 + 死信队列)
 */
@Configuration
public class RabbitTtlDlxConfig {
    public static final String QUEUE_NAME_TTL = "QUEUE_NAME_TTL_1";
    public static final String EXCHANGE_NAME_TTL = "EXCHANGE_NAME_TTL_1";
    public static final String QUEUE_NAME_DEAD_LETTER = "QUEUE_NAME_DEAD_LETTER";
    public static final String EXCHANGE_NAME_DLX = "EXCHANGE_NAME_DLX";
    //统配符
    public static final String ROUTING_KEY_DLX = "EXPIRE.#";
    public static final String ROUTING_KEY_DEAD_LETTER = "EXPIRE.10";
    public static final String ROUTING_KEY_TTL = "EXPIRE_TTL_10";
/**
 * 直连交换机, 普通队列-交换机 : EXCHANGE_NAME_TTL_1 -> QUEUE_NAME_TTL 路由键: ROUTING_KEY_TTL
 * 主题交换机, 死信队列 : EXCHANGE_NAME_DLX -> QUEUE_NAME_DEAD_LETTER 通配符: EXPIRE.#
 */

    /**
     * 1. Queue 队列
     */
    @Bean(QUEUE_NAME_TTL)
    public Queue queue() {
        /*
         * 1. 设置队列的过期时间 30s
         * 2. 绑定DLX
         * 3. 设置routing key（注意：这里设置的是路由到死信Queue的路由，并不是设置binding关系的路由）
         */
        //老版本用这个,或者new queue()形式;
        Map<String , Object> arguments = new HashMap<>();
        arguments.put("x-message-ttl" , 30000);
        //声明当前队列绑定的死信交换机
        arguments.put("x-dead-letter-exchange",EXCHANGE_NAME_DLX);
        //声明当前队列的死信路由键 如果没有指定，则使用原队列的路由键：
        arguments.put("x-dead-letter-routing-key" , ROUTING_KEY_DEAD_LETTER);
        return QueueBuilder.durable(QUEUE_NAME_TTL).withArguments(arguments).build();
        //最新版本用如下方式
//        return QueueBuilder.durable(QUEUE_NAME_TTL).ttl(10000).deadLetterExchange(EXCHANGE_NAME_DLX).deadLetterRoutingKey(ROUTING_KEY_DEAD_LETTER).build();
    }

    /**
     * 2. exchange
     *      直连交换机
     */
    @Bean(EXCHANGE_NAME_TTL)
    public Exchange exchange() {
        return ExchangeBuilder.directExchange(EXCHANGE_NAME_TTL).durable(true).build();
    }

    /**
     * 3. 队列和交互机绑定关系 Binding
     */
    @Bean
    public Binding bindExchange(@Qualifier(QUEUE_NAME_TTL) Queue queue, @Qualifier(EXCHANGE_NAME_TTL) Exchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY_TTL).noargs();
    }

/****************************************分割*******************************************/
    /**
     * 4. 死信队列
     */
    @Bean(QUEUE_NAME_DEAD_LETTER)
    public Queue deadLetterQueue() {
        return QueueBuilder.durable(QUEUE_NAME_DEAD_LETTER).build();
    }

    /**
     * 5. dlx 死信交换机
     *  实际上死信交换机就是一个普通交换机;是某个队列绑定的一个特殊交换机,专门用于处理该队列的死亡消息;
     *  主题交换机 : topicExchange
     */
    @Bean(EXCHANGE_NAME_DLX)
    public Exchange exchangeDlx() {
        return ExchangeBuilder.topicExchange(EXCHANGE_NAME_DLX).durable(true).build();
        //老版本也可以用这个来声明一个交换机
//        return new TopicExchange(EXCHANGE_NAME_DLX,true,false);
    }

    /**
     * 6. 队列和交互机绑定关系 Binding
     */
    @Bean
    public Binding bindDlxExchange(@Qualifier(QUEUE_NAME_DEAD_LETTER) Queue queue, @Qualifier(EXCHANGE_NAME_DLX) Exchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY_DLX).noargs();
    }
}
